"""
异常处理模块
提供统一的异常类和处理函数
"""
import logging
from enum import Enum
from typing import Dict, Any, Optional
from fastapi import HTTPException

logger = logging.getLogger(__name__)

class ErrorCode(Enum):
    """统一错误码枚举"""
    # 通用错误 1xxx
    INTERNAL_ERROR = 1000
    VALIDATION_ERROR = 1001
    CONFIGURATION_ERROR = 1002
    
    # 数据集相关错误 2xxx
    DATASET_NOT_FOUND = 2001
    DATASET_INVALID_FORMAT = 2002
    DATASET_EMPTY = 2003
    DATASET_CORRUPTED = 2004
    
    # 模型相关错误 3xxx
    MODEL_NOT_FOUND = 3001
    MODEL_LOAD_FAILED = 3002
    MODEL_INVALID_TYPE = 3003
    MODEL_TRAINING_FAILED = 3004
    
    # 训练相关错误 4xxx
    TRAINING_TASK_NOT_FOUND = 4001
    TRAINING_ALREADY_RUNNING = 4002
    TRAINING_PARAMETERS_INVALID = 4003
    TRAINING_RESOURCE_INSUFFICIENT = 4004

class BaseCustomException(Exception):
    """自定义异常基类"""
    
    def __init__(
        self, 
        message: str, 
        error_code: ErrorCode = ErrorCode.INTERNAL_ERROR,
        details: Optional[Dict[str, Any]] = None
    ):
        self.message = message
        self.error_code = error_code
        self.details = details or {}
        super().__init__(self.message)

class ValidationException(BaseCustomException):
    """验证异常"""
    
    def __init__(self, message: str, details: Optional[Dict[str, Any]] = None):
        super().__init__(message, ErrorCode.VALIDATION_ERROR, details)

class NetworkException(BaseCustomException):
    """网络异常"""
    
    def __init__(self, message: str, details: Optional[Dict[str, Any]] = None):
        super().__init__(message, ErrorCode.NETWORK_ERROR, details)

class NotFoundException(BaseCustomException):
    """资源未找到异常"""
    
    def __init__(self, message: str, details: Optional[Dict[str, Any]] = None):
        super().__init__(message, ErrorCode.DATASET_NOT_FOUND, details)

class DatasetException(BaseCustomException):
    """数据集异常"""
    
    def __init__(
        self, 
        message: str, 
        error_code: ErrorCode = ErrorCode.DATASET_NOT_FOUND,
        details: Optional[Dict[str, Any]] = None
    ):
        super().__init__(message, error_code, details)

class ModelException(BaseCustomException):
    """模型异常"""
    
    def __init__(
        self, 
        message: str, 
        error_code: ErrorCode = ErrorCode.MODEL_NOT_FOUND,
        details: Optional[Dict[str, Any]] = None
    ):
        super().__init__(message, error_code, details)

class TrainingException(BaseCustomException):
    """训练异常"""
    
    def __init__(
        self, 
        message: str, 
        error_code: ErrorCode = ErrorCode.TRAINING_TASK_NOT_FOUND,
        details: Optional[Dict[str, Any]] = None
    ):
        super().__init__(message, error_code, details)

class ConfigurationException(BaseCustomException):
    """配置相关异常"""
    pass

# 异常处理器
class ExceptionHandler:
    """统一异常处理器"""
    
    @staticmethod
    def handle_exception(e: Exception, default_message: str = "系统错误") -> HTTPException:
        """处理异常并返回标准化的HTTP异常"""
        
        if isinstance(e, BaseCustomException):
            # 记录错误日志
            logger.error(
                f"业务异常: {e.error_code.name} - {e.message}",
                extra={
                    "error_code": e.error_code.value,
                    "details": e.details
                }
            )
            
            return HTTPException(
                status_code=ExceptionHandler._get_http_status_code(e.error_code),
                detail={
                    "error_code": e.error_code.value,
                    "error_type": e.error_code.name,
                    "message": e.message,
                    "details": e.details
                }
            )
        else:
            # 处理未知异常
            logger.error(f"未处理异常: {type(e).__name__} - {str(e)}", exc_info=True)
            
            return HTTPException(
                status_code=500,
                detail={
                    "error_code": ErrorCode.INTERNAL_ERROR.value,
                    "error_type": ErrorCode.INTERNAL_ERROR.name,
                    "message": default_message,
                    "details": {"original_error": str(e)}
                }
            )
    
    @staticmethod
    def _get_http_status_code(error_code: ErrorCode) -> int:
        """根据错误码获取HTTP状态码"""
        status_code_mapping = {
            # 1xxx - 客户端错误
            ErrorCode.VALIDATION_ERROR: 400,
            ErrorCode.CONFIGURATION_ERROR: 400,
            
            # 2xxx - 数据集相关
            ErrorCode.DATASET_NOT_FOUND: 404,
            ErrorCode.DATASET_INVALID_FORMAT: 400,
            ErrorCode.DATASET_EMPTY: 400,
            ErrorCode.DATASET_CORRUPTED: 422,
            
            # 3xxx - 模型相关
            ErrorCode.MODEL_NOT_FOUND: 404,
            ErrorCode.MODEL_LOAD_FAILED: 422,
            ErrorCode.MODEL_INVALID_TYPE: 400,
            ErrorCode.MODEL_TRAINING_FAILED: 422,
            
            # 4xxx - 训练相关
            ErrorCode.TRAINING_TASK_NOT_FOUND: 404,
            ErrorCode.TRAINING_ALREADY_RUNNING: 409,
            ErrorCode.TRAINING_PARAMETERS_INVALID: 400,
            ErrorCode.TRAINING_RESOURCE_INSUFFICIENT: 503,
        }
        
        return status_code_mapping.get(error_code, 500)

    @staticmethod
    def safe_set_error_message(task, error_message: str) -> bool:
        """安全地设置任务错误信息"""
        try:
            if hasattr(task, 'error_message'):
                task.error_message = error_message
                return True
            else:
                logger.warning(f"任务对象没有error_message字段，无法设置错误信息: {error_message}")
                return False
        except Exception as e:
            logger.error(f"设置错误信息失败: {e}")
            return False

# 装饰器：自动异常处理
def handle_exceptions(default_message: str = "操作失败"):
    """
    异常处理装饰器
    
    Args:
        default_message: 默认错误消息
    """
    def decorator(func):
        def wrapper(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except Exception as e:
                raise ExceptionHandler.handle_exception(e, default_message)
        return wrapper
    return decorator 